﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Web;
using System.ServiceModel;
using System.IO;
using System.Data;
using System.Drawing;
using System.Web.UI.WebControls;

    public class ModdbFrontEnd
    {
        Moddb08_WCF.Itest client;
        WebChannelFactory<Moddb08_WCF.Itest> factory;
        
        public ModdbFrontEnd()
        {
            WSHttpBinding binding = new WSHttpBinding();
            binding.MaxReceivedMessageSize = 2000000000;
            factory = new WebChannelFactory<Moddb08_WCF.Itest>(new Uri("http://localhost:2049/test.svc"));
            ((WebHttpBinding)factory.Endpoint.Binding).MaxReceivedMessageSize = 2000000000;
            client = factory.CreateChannel();
            
           
        }

        public Moddb08_WCF.Tables GetAllTables()
        {
            Moddb08_WCF.Tables tables = client.GetAllTables();
            return tables;
        }

        public Moddb08_WCF.Columns GetAllColumns(string tableName)
        {
            return client.GetAllColumnsOfTable(tableName);
        }

        public Moddb08_WCF.Rows GetAllRows(string tableName)
        {
            return client.GetAllRows(tableName);
        }

        public bool CreateTable(string tableName)
        {
            client.AddNewTable(new Moddb08_WCF.Table(tableName));
            return true;

        }

        public Stream GetColumnData(string tableName, string rowID, string columnName)
        {
            return client.GetColumnData(tableName, rowID, columnName);
        }

        public byte[] GetColumnByteData(string tableName, string rowID, string columnName)
        {
            return GetBytesFromStream(GetColumnData(tableName, rowID, columnName));
        }

        public DataTable GetDataTable(string table)
        {
            DataTable dataTable = new DataTable(table);
            Moddb08_WCF.Columns columns = GetAllColumns(table);
            foreach (Moddb08_WCF.Column col in columns)
            {

                if (col.Mime.Equals("text/plain"))
                {
                    dataTable.Columns.Add(new DataColumn(col.Name, ParseDataType(col.Type)));
                    if (col.Name.ToUpper().Equals("ID"))
                    {
                        dataTable.Columns[col.Name].AutoIncrement = true;
                        dataTable.Columns[col.Name].ReadOnly = true;
                    }
                }
                else
                {
                    dataTable.Columns.Add(new DataColumn(col.Name, typeof(Uri)));
                }

            }
            Moddb08_WCF.Rows rows = GetAllRows(table);
            foreach (Moddb08_WCF.Row row in rows)
            {
                DataRow dataRow =  dataTable.NewRow();
                foreach (Moddb08_WCF.Column col in columns)
                {
                    
                    if(col.Mime.Equals("text/plain"))
                    {
                        dataRow[col.Name] = ConvertByteArrayToObject(GetBytesFromStream(GetColumnData(table, row.Id.ToString(), col.Name)), dataTable.Columns[col.Name].DataType, col.Mime);
                    }
                    else
                    {
                        string url = "BinaryDataRetrival.ashx?tableName=" + table +  "&rowId=" + row.Id + "&columnName=" + col.Name;
                        
                        Uri newUri = new Uri(url, UriKind.Relative);
                        dataRow[col.Name] = newUri;

                    }
                }

                dataTable.Rows.Add(dataRow);
            }
            return dataTable;

        }





        # region Private Methods

        /// <summary>
        /// Get the datatype of the data
        /// </summary>
        /// <param name="dataType">The name of the datatype</param>
        /// <returns>The datatype object of the data</returns>
        private Type ParseDataType(string dataType)
        {
            if (dataType.ToUpper().Equals("INT") || dataType.ToUpper().Equals("INTEGER"))
            {
                return typeof(int);
            }
            else if (dataType.ToUpper().Equals("SMALLINT"))
            {
                return typeof(Int16);
            }
            else if (dataType.ToUpper().Equals("DECIMAL"))
            {
                return typeof(decimal);
            }
            else if (dataType.ToUpper().Equals("NCHAR") || dataType.ToUpper().Equals("VARCHAR") ||
                        dataType.ToUpper().Equals("TEXT"))
            {
                return typeof(string);
            }
            else if (dataType.ToUpper().Equals("IMAGE") || dataType.ToUpper().Equals("BLOB"))
            {
                return typeof(byte[]);
            }
            else if (dataType.ToUpper().Equals("MONEY"))
            {
                return typeof(Decimal);
            }
            else if (dataType.ToUpper().Equals("DATE") || dataType.ToUpper().Equals("DATETIME"))
            {
                return typeof(DateTime);
            }
            else
            {
                return null;
            }
        }

        private byte[] GetBytesFromStream(Stream data)
        {
            List<byte> list = new List<byte>();
            BinaryReader reader = new BinaryReader(data);
            try
            {
                while (true)
                {
                    list.Add(reader.ReadByte());
                }
            }
            catch(EndOfStreamException)
            {
                byte[] array = new byte[list.Count];
                for (int i = 0; i < list.Count; i++)
                {
                    array[i] = list[i];
                }
                return array;
            }
        }


        private Object ConvertByteArrayToObject(byte[] data, Type type, string mime)
        {
            if(type.Equals(typeof(Int32)))
            {

                if (mime.Equals("text/plain"))
                {
                    System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();

                    return int.Parse(enc.GetString(data));
                }
                return BitConverter.ToInt32(data, 0);
            }else if(type.Equals(typeof(Int16)))
            {
                return BitConverter.ToInt16(data, 0);
            }else if(type.Equals(typeof(byte[])))
            {
                return data;
            }else if(type.Equals(typeof(string)))
            {
                System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
                return enc.GetString(data);
            }
            else
            {
                return null;
            }
        }
        #endregion
    }
